package scalab.caches

import cdp.{TimestampCDP, DigestCDP}
import scalab.core.{Cache, CacheCorePolicy, ChangeDetectionPolicy, EvictionPolicy}
import scalab.core.dependencies.Dependency
import scalab.core.component.{Task, Filter}
import java.io.File

sealed trait NoCCP extends CacheCorePolicy{
	import java.io.{FileNotFoundException, IOException}
	//final override protected def locker(task: Task): String = cacheDirectory + "lock" 
	final protected def load(task: Task): Boolean = {
		setTaskProductDir(task, taskDirectory(task))
		Cache.createProductDirectory(task)
		task.invalidateSources
		true
	}
	final protected def load(filter: Filter): Boolean = true
	final protected def store(task: Task): Boolean = {
		import java.io.FileOutputStream
		var fos: FileOutputStream = null
		try{
			fos = new FileOutputStream(cacheDirectory + task.id + ".prods")
		}
		catch{
			case fnfe: FileNotFoundException => error(fnfe.getMessage)
				return false
			case se: SecurityException => error(se.getMessage)
				return false
		}

		try{
			fos.write(Cache.serialize(task.productDependencies))
			true
		}
		catch{
			case ioe: IOException => error(ioe.getMessage)
				false
		}
		finally{
			fos.close
		}
	}
	final protected def store(filter: Filter): Boolean = true
	final def getCachedProductDirs(taskDir: File): Iterable[File] = Nil
	override final def cacheSize: Long = 0
	final protected def free(file: File): Long = 0
	def getRunProducts(task: Task, sources: Iterable[Dependency]): (Boolean, Option[Set[Dependency]]) = {
		import java.io.FileInputStream
		var fis: FileInputStream = null
		try{
			fis = new FileInputStream(cacheDirectory + task.id + ".prods")
		}
		catch{
			case fnfe: FileNotFoundException => error(fnfe.getMessage)
				return (false, None)
			case se: SecurityException => error(se.getMessage)
				return (false, None)
		}

		try{
			var nbRead = 0
			val dataBytes: Array[byte] = new Array(1024)
			var allBytes: Array[byte] = new Array(0)
			do{
				nbRead = fis.read(dataBytes)
				allBytes = allBytes ++ dataBytes
			}while(nbRead != -1)
			(true, Some(Cache.deserialize[Set[Dependency]](allBytes)))
		}
		catch{
			case ioe: IOException => error(ioe.getMessage)
				(false, None)
		}
		finally{
			fis.close
		}
	}
	
}

sealed trait NoCEP extends EvictionPolicy{
	def evictionOrder(files: Iterable[File]): Stream[File] = Stream.empty
}

object NoCache{
	def apply(): Cache = new NoCCP with TimestampCDP with NoCEP{
		lazy val name: String = "NoCache"
	}

	def apply(timestamp: Boolean): Cache = 
		if(timestamp)new NoCCP with TimestampCDP with NoCEP{
			lazy val name: String = "NoTCache"
		}
		else new NoCCP with DigestCDP with NoCEP{
			lazy val name: String = "NoDCache"
		}
}
